package com.alibaba.cirtus.ots.application.adapter.ability.facade.serviceV2.crm;

import com.alibaba.acm.shaded.com.google.common.collect.Lists;
import com.alibaba.cirtus.ots.application.adapter.ability.model.enums.MnSAPStatus;
import com.alibaba.cirtus.ots.application.adapter.ability.model.sdo.PlanScItemReturnCountSDO;
import com.alibaba.citrus.ots.common.annotation.EpochTransactional;
import com.alibaba.citrus.ots.common.annotation.ProcessInvoker;
import com.alibaba.citrus.ots.common.exception.FacadeException;
import com.alibaba.citrus.ots.common.util.CalculatePercentage;
import com.alibaba.citrus.ots.common.util.SapAndCrmFieldDealUtils;
import com.alibaba.citrus.ots.common.util.SpringContextUtil;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcorder.model.dto.BaselineGetOrganizationByCodes2Request;
import com.epoch.app.bcorder.model.dto.BaselineGetOrganizationByCodes2Response;
import com.epoch.app.bcorder.model.dto.BaselineGetOrganizationById2Request;
import com.epoch.app.bcorder.model.dto.BaselineGetOrganizationByTypeRequest;
import com.epoch.app.bcorder.model.dto.BatchQueryCompanyRequest;
import com.epoch.app.bcorder.model.dto.MonthlyPlanOfCcommerceLoadListRequest;
import com.epoch.app.bcorder.model.dto.OrganizationSDO;
import com.epoch.app.bcorder.model.dto.ScItemSDO;
import com.epoch.app.bcorder.model.dto.SearchScItemRequest;
import com.epoch.app.bcorder.sales_plan.monthlyplanofccommerce.model.MonthlyPlanOfCcommerce;
import com.epoch.app.bcorder.sales_plan.monthlyplanofccommerce.service.MonthlyPlanOfCcommerceService;
import com.epoch.app.bcorder.sales_plan.planscitem.dto.BatchQueryByBizIdRequest;
import com.epoch.app.bcorder.sales_plan.planscitem.model.PlanScItem;
import com.epoch.app.bcorder.sales_plan.planscitem.service.PlanScItemService;
import com.epoch.app.bcorder.sales_plan.planscitemextend.dto.BatchSavePlanScItemExtendRequest;
import com.epoch.app.bcorder.sales_plan.planscitemextend.dto.BatchSavePlanScItemExtendResponse;
import com.epoch.app.bcorder.sales_plan.planscitemextend.model.PlanScItemExtend;
import com.epoch.app.bcorder.sales_plan.planscitemextend.service.PlanScItemExtendService;
import com.epoch.app.bcorder.sales_plan.salesplan.dto.LoadSalesPlanListRequest;
import com.epoch.app.bcorder.sales_plan.salesplan.dto.UpdateSalesPlanResponse;
import com.epoch.app.bcorder.sales_plan.salesplan.model.SalesPlan;
import com.epoch.app.bcorder.sales_plan.salesplan.service.SalesPlanService;
import com.epoch.app.bcorder.service.BaseDataService;
import com.epoch.app.bcorder.service.BcOrderService;
import com.epoch.app.otsapplicationadaptersdk.crm.MnCrmCommResponse;
import com.epoch.app.otsapplicationadaptersdk.crm.MnCrmCommSDO;
import com.epoch.app.otsapplicationadaptersdk.crm.MnCrmIf002SDO;
import com.epoch.app.otsapplicationadaptersdk.crmv2.mncrmif002v2.dto.OmniPlanReplyExtendRequest;
import com.epoch.app.otsapplicationadaptersdk.crmv2.mncrmif002v2.service.MnCrmIf002V2Service;
import com.epoch.app.otsapplicationadaptersdk.sap.MnCrmIf002Request;
import com.google.common.collect.Maps;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author zhoubc
 * @description: CRM请求平台月度计划回复
 * @date 2021/9/25 1:07
 */
@Component
public class MnCrmIf002V2ServiceImpl implements MnCrmIf002V2Service {
    private final static Log log = Log.getLogger(com.alibaba.cirtus.ots.application.adapter.ability.facade.service.crm.MnCrmIf002ServiceImpl.class);

    @Resource
    private PlanScItemService planScItemService;

    @Resource
    private SalesPlanService salesPlanService;

    @Resource
    private BaseDataService baseDataService;

    @Resource
    private PlanScItemExtendService planScItemExtendService;

    @Resource
    private BcOrderService bcOtsService;

    @Resource
    private MonthlyPlanOfCcommerceService monthlyPlanOfCcommerceService;

    @ProcessInvoker(remark = "MnCrmIf002Service", errorCode = "OTS-02-007-00-16-999", printLog = true)
    @Override
    public MnCrmCommResponse externalUpdateReplySalePlan(MnCrmIf002Request mnCrmIf002Request) {
        // 1、设置消息头
        MnCrmCommResponse commResponse = MnCrmCommResponse.builder().build();
        commResponse.setMessageId(mnCrmIf002Request.getMessageHeader().getMessageId());
        commResponse.setInterfacePath(mnCrmIf002Request.getMessageHeader().getInterfacePath());
        List<MnCrmIf002SDO> data = mnCrmIf002Request.getData();
        if (CollectionUtils.isEmpty(data)) {
            MnCrmCommSDO commSDO = MnCrmCommSDO.builder().resultType(MnSAPStatus.ERROR.getCode()).resultMessage("入参数组不可为空").build();
            commResponse.setData(commSDO);
            log.error("MnCrmIf002ServiceImpl#externalUpdateReplySalePlan_fail {}", JSONObject.toJSONString(commSDO));
            return commResponse;
        }

        List<String> superiorSalesOrgCodeList = Lists.newArrayList("6000","6004");
        // 2、筛选电商月度计划和分子公司月度计划
        List<MnCrmIf002SDO> salesPlanReplays = data.stream().filter(it -> superiorSalesOrgCodeList.contains(it.getSalesOrganizationCode())).collect(Collectors.toList());
        List<MnCrmIf002SDO> eCommerceSalesPlanReplay = data.stream().filter(it -> "1171".equals(it.getSalesOrganizationCode())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(salesPlanReplays) && CollectionUtils.isEmpty(eCommerceSalesPlanReplay)) {
            log.error("没有计划回复货品,请查看请求入参");
            MnCrmCommSDO commSDO = MnCrmCommSDO.builder().resultType(MnSAPStatus.ERROR.getCode()).resultMessage("没有回复货品").build();
            commResponse.setData(commSDO);
            return commResponse;
        }

        //电商月度计划
        String commerceErrMsg = null;
        if (CollectionUtils.isNotEmpty(eCommerceSalesPlanReplay)) {
            commerceErrMsg = processCommerceSalesPlan(eCommerceSalesPlanReplay);
            if (CollectionUtils.isEmpty(salesPlanReplays)) {
                MnCrmCommSDO commSDO = MnCrmCommSDO.builder().resultType(MnSAPStatus.SUCCESS.getCode()).resultMessage("电商月度计划回复成功").build();
                if(StringUtils.isNotBlank(commerceErrMsg)){
                    commSDO = MnCrmCommSDO.builder().resultType(MnSAPStatus.ERROR.getCode()).resultMessage(commerceErrMsg).build();
                }
                commResponse.setData(commSDO);
                return commResponse;
            }
        }

        // 2、在货品-业务单元维度获取月度计划明细统计数据
        Map<String,Object> resultMap = Maps.newHashMap();
        Map<String,String> notExistOrgMap = Maps.newHashMap();
        Map<String,String> notExistPlanMap = Maps.newHashMap();
        Map<String,String> notExistItemsMap = Maps.newHashMap();
        Map<String,String> notExistPlanScItemsMap = Maps.newHashMap();
        List<String> errorPlanTimeCustomerCodes = Lists.newArrayList();

        if (CollectionUtils.isNotEmpty(salesPlanReplays)) {
            try {
                // 3 过滤是否有不合格的数据（货品不存在，没有汇总数据）
                // 3.1 先获取所有公司编码   计划时间+业务组织单元对应客户编码
                Set<String> customerCodesSet = salesPlanReplays.stream().map(x->featchKey(x)).collect(Collectors.toSet());
                Map</* CustomerCode 计划时间+业务组织单元对应客户编码 */String, /* 回复货品列表 */List<MnCrmIf002SDO>> orgUnitRespScItemMap = Maps.newHashMap();
                Map</* CustomerCode 计划时间+业务组织单元对应客户编码 */String, /* 计划货品列表 */List<PlanScItem>> orgUnitPlanScItemMap = Maps.newHashMap();
                Map</* CustomerCode 计划时间+业务组织单元对应客户编码 */String, /* 调整计划 */SalesPlan> orgUnitSalePlanMap = Maps.newHashMap();
                Map</* CustomerCode 计划时间+业务组织单元对应客户编码 */String, /* 业务单元编码 */String> orgUnitCodeMap = Maps.newHashMap();
                Map</* CustomerCode 计划时间+业务组织单元对应客户编码 */String, /* 货品Map */Map<String, ScItemSDO>> orgUnitScItemMap = Maps.newHashMap();
                List<String> checkSuccessCustomerCodes = new ArrayList<>();

                //3.2 逐个公司扫描数据
                for (String key : customerCodesSet) {
                    String[] array = key.split("#");
                    String customerCode = array[1];
                    //计划时间x客户x货品
                    List<MnCrmIf002SDO> planTimeAndCustomerAndScItemList = salesPlanReplays.stream().filter(it -> featchKey(it).equals(key)).collect(Collectors.toList());
                    //判断公司是否存在
                    MnCrmIf002SDO crmIf002SDO = planTimeAndCustomerAndScItemList.get(0);
                    String orgBusinessUnitCode = getOrgBusinessUnitCode(crmIf002SDO);
                    if(StringUtils.isBlank(orgBusinessUnitCode)){
                        log.info("MnCrmIf002ServiceImpl#externalUpdateReplySalePlan_fail 组织不存在,customerCode：{}", crmIf002SDO.getCustomerCode());
                        notExistOrgMap.put(key,customerCode);
                        errorPlanTimeCustomerCodes.add(key);
                        continue;
                    }
                    orgUnitCodeMap.put(key, orgBusinessUnitCode);

                    //根据公司和计划时间获取平台提报的货品集合
                    List<String> itemCodes = getScItemCodesBy002SDOs(planTimeAndCustomerAndScItemList);
                    Map<String, ScItemSDO> itemByOuterIds = getScItemByOuterIds(itemCodes);
                    orgUnitScItemMap.put(key, itemByOuterIds);

                    //查询计划提报货品
                    List<PlanScItem> planScItemList = getPlanScItemListByTimeAndBusiness(orgBusinessUnitCode, crmIf002SDO, orgUnitSalePlanMap);
                    if (CollectionUtils.isEmpty(planScItemList)) {
                        String errMsg = "planTime:" + crmIf002SDO.getPlanTime() + "，orgBusinessUnitCode："+ orgBusinessUnitCode;
                        log.info("MnCrmIf002ServiceImpl#externalUpdateReplySalePlan_fail 月度计划非待回复状态或月度计划没有提报货品 " +errMsg);
                        notExistPlanMap.put(key,errMsg);
                        errorPlanTimeCustomerCodes.add(key);
                        continue;
                    }
                    orgUnitPlanScItemMap.put(key, planScItemList);
                    Map<String, PlanScItem> planScItemMap = planScItemList.stream().collect(Collectors.toMap(PlanScItem::getScItemId, o -> o));

                    //判断是否有不存在的货品
                    boolean noOk = false;
                    for (MnCrmIf002SDO if002SDO : planTimeAndCustomerAndScItemList) {
                        if (!itemByOuterIds.containsKey(if002SDO.getScItemCode())) {
                            log.info("MnCrmIf002ServiceImpl#externalUpdateReplySalePlan_fail 货品不存在或不可用，scItemCode={}", if002SDO.getScItemCode());
                            notExistItemsMap.put(key,if002SDO.getScItemCode());
                            noOk = true;
                            continue;
                        } else {
                            ScItemSDO scItemSDO = itemByOuterIds.get(if002SDO.getScItemCode());
                            if (!planScItemMap.containsKey(scItemSDO.getScItemId())) {
                                String errMsg = "planTime:" + crmIf002SDO.getPlanTime() + "，orgBusinessUnitCode："+ orgBusinessUnitCode + "，scItemCode:" + scItemSDO.getOuterId();
                                log.info("MnCrmIf002ServiceImpl#externalUpdateReplySalePlan_fail 货品不在提报货品中，详情={}", errMsg);
                                notExistPlanScItemsMap.put(key,errMsg);
                                noOk = true;
                                continue;
                            }
                        }
                    }
                    if(noOk){
                        errorPlanTimeCustomerCodes.add(key);
                        continue;
                    }
                    orgUnitRespScItemMap.put(key, planTimeAndCustomerAndScItemList);
                    checkSuccessCustomerCodes.add(key);
                }

                Map<String,Map<String,Object>> errorKeyMap = Maps.newHashMap();
                for (String errorKey:errorPlanTimeCustomerCodes) {
                    String[] array = errorKey.split("#");
                    Map<String,Object> result = Maps.newHashMap();
                    // 4、哪个计划时间+companyCode存在不合规数据，就返回错误
                    if (StringUtils.isNotBlank(notExistOrgMap.get(errorKey))) {
                        result.put("组织不存在，客户编码", notExistOrgMap.get(errorKey));
                    }
                    if (StringUtils.isNotBlank(notExistItemsMap.get(errorKey))) {
                        result.put("货品不可用或不存在，货品编码列表", notExistItemsMap.get(errorKey));
                    }
                    if (StringUtils.isNotBlank(notExistPlanMap.get(errorKey))) {
                        result.put("月度计划非待回复状态或月度计划没有提报货品", notExistPlanMap.get(errorKey));
                    }
                    if (StringUtils.isNotBlank(notExistPlanScItemsMap.get(errorKey))) {
                        result.put("回复货品对应月度计划提报货品不存在，详情", notExistPlanScItemsMap.get(errorKey));
                    }
                    errorKeyMap.put("planTime="+array[0]+",customerCode="+array[1]+",错误原因",result);
                }
                if(MapUtils.isNotEmpty(errorKeyMap)){
                    resultMap.put("分子公司月度计划回复失败，回复失败的月度计划",errorKeyMap);
                }

                // 5、逐个公司进行回复
                Map</* 计划时间+companyCode */String, List<PlanScItemExtend>> companyScItemExtendMap = Maps.newHashMap();
                for (String key : checkSuccessCustomerCodes) {
                    // 5.1 crm回复的货品
                    List<MnCrmIf002SDO> if002SDOS = orgUnitRespScItemMap.get(key);
                    if(CollectionUtils.isEmpty(if002SDOS)){
                        log.info("MnCrmIf002ServiceImpl#externalUpdateReplySalePlan_crm_customer_resp_scItem_is_null,customer_code={}",key);
                        continue;
                    }
                    // 5.2 获取订单平台提报的货品
                    List<PlanScItem> reportItems = orgUnitPlanScItemMap.get(key);
                    if(CollectionUtils.isEmpty(reportItems)){
                        log.info("MnCrmIf002ServiceImpl#externalUpdateReplySalePlan_ots_customer_report_scItem_is_null,customer_code={}",key);
                        continue;
                    }

                    Map<String, PlanScItem> planScItemMap = reportItems.stream().collect(Collectors.toMap(PlanScItem::getScItemId, o -> o));
                    for (MnCrmIf002SDO mnCrmIf002SDO : if002SDOS) {
                        // 5.3 给回复量赋值
                        PlanScItem planScItem = buildPlanScItem(planScItemMap, orgUnitSalePlanMap, orgUnitScItemMap.get(key), mnCrmIf002SDO);
                        if (Objects.nonNull(planScItem)) {
                            planScItemMap.put(planScItem.getScItemId(), planScItem);
                        }
                    }
                    // 5.4 入库前参数构建
                    List<PlanScItem> list = Lists.newArrayList(planScItemMap.values());
                    if (CollectionUtils.isNotEmpty(list)) {
                        List<PlanScItemExtend> extendList = list.stream().map(it -> {
                            PlanScItemExtend planScItemExtend = new PlanScItemExtend();
                            BeanUtils.copyProperties(it, planScItemExtend);
                            // 计算上中下旬回复金额
                            Long costInsuranceFreight = it.getCostInsuranceFreight();
                            costInsuranceFreight = Objects.isNull(costInsuranceFreight) ? 0L : costInsuranceFreight;

                            Long monthFirstReturnCount = Objects.isNull(it.getMonthFirstReturnCount()) ? 0L : it.getMonthFirstReturnCount().longValue();
                            Long monthMiddleReturnCount = Objects.isNull(it.getMonthMiddleReturnCount()) ? 0L : it.getMonthMiddleReturnCount().longValue();
                            Long monthLastReturnCount = Objects.isNull(it.getMonthLastReturnCount()) ? 0L : it.getMonthLastReturnCount().longValue();

    //                        //crm回复的回复量，按上中下旬的回复量占比进行比例分配
    //                        int monthFirstCount = Objects.isNull(it.getMonthFirstCount())?0:it.getMonthFirstCount();
    //                        int monthMiddleCount = Objects.isNull(it.getMonthMiddleCount())?0:it.getMonthMiddleCount();
    //                        int monthLastCount = Objects.isNull(it.getMonthLastCount())?0:it.getMonthLastCount();
    //                        //总提报量
    //                        int planTotalCount=it.getMonthCount();
    //                        //总回复数量
    //                        Long replyTotalCount=monthFirstReturnCount+monthMiddleReturnCount+monthLastReturnCount;

    //                        Long firstReturnCount;
    //                        Long middleReturnCount;
    //                        Long lastReturnCount;
    //
    //                        long firstReturnCountVice = (replyTotalCount == 0L) ? 0L : (new BigDecimal(monthFirstCount).divide(new BigDecimal(planTotalCount), 4, RoundingMode.DOWN).multiply(new BigDecimal(replyTotalCount))).longValue();
    //                        long middleReturnCountVice = (replyTotalCount == 0L) ? 0L : (new BigDecimal(monthMiddleCount).divide(new BigDecimal(planTotalCount), 4, RoundingMode.DOWN).multiply(new BigDecimal(replyTotalCount))).longValue();
    //                        //如果供小于求
    //                        if (replyTotalCount.intValue()<planTotalCount){
    //                            firstReturnCount = firstReturnCountVice;
    //                            middleReturnCount = middleReturnCountVice;
    //                            lastReturnCount = replyTotalCount-firstReturnCount-middleReturnCount;
    //                        }else if (replyTotalCount.intValue()==planTotalCount){
    //                            firstReturnCount=(long)monthFirstCount;
    //                            middleReturnCount=(long)monthMiddleCount;
    //                            lastReturnCount=(long)monthLastCount;
    //                        }else {
    //                            firstReturnCount = firstReturnCountVice;
    //                            middleReturnCount = middleReturnCountVice;
    //                            lastReturnCount = replyTotalCount-firstReturnCount-middleReturnCount;
    //                        }

    //                        planScItemExtend.setMonthFirstReturnCount(firstReturnCount.intValue());
    //                        planScItemExtend.setMonthMiddleReturnCount(middleReturnCount.intValue());
    //                        planScItemExtend.setMonthLastReturnCount(lastReturnCount.intValue());
                            //产品牧常要求 002crm回复量是多少对应上中下旬落库就多少 不用其他按比例分配落库
                            planScItemExtend.setMonthFirstReturnCount(monthFirstReturnCount.intValue());
                            planScItemExtend.setMonthMiddleReturnCount(monthMiddleReturnCount.intValue());
                            planScItemExtend.setMonthLastReturnCount(monthLastReturnCount.intValue());

                            planScItemExtend.setMonthFirstCompanyTaskCount(monthFirstReturnCount.intValue());
                            planScItemExtend.setMonthMiddleCompanyTaskCount(monthMiddleReturnCount.intValue());
                            planScItemExtend.setMonthLastCompanyTaskCount(monthLastReturnCount.intValue());
                            Long companyTaskCount = monthFirstReturnCount+monthMiddleReturnCount+monthLastReturnCount;
                            planScItemExtend.setCompanyTaskCount(companyTaskCount.intValue());

                            planScItemExtend.setMonthFirstReturnMoney(costInsuranceFreight * monthFirstReturnCount.intValue());
                            planScItemExtend.setMonthMiddleReturnMoney(costInsuranceFreight * monthMiddleReturnCount.intValue());
                            planScItemExtend.setMonthLastReturnMoney(costInsuranceFreight * monthLastReturnCount.intValue());

                            planScItemExtend.setGmtCreate(new Date());
                            planScItemExtend.setGmtModified(new Date());
                            planScItemExtend.setModel(1);
                            planScItemExtend.setModelId(String.valueOf(planScItemExtend.getPlanId()));
                            return planScItemExtend;
                        }).collect(Collectors.toList());

                        companyScItemExtendMap.put(key, extendList);
                    }
                }

                // 批量更新月度计划状态，从循环中单独抽出，控制事务范围，提升性能；
                SpringContextUtil.getBean(com.alibaba.cirtus.ots.application.adapter.ability.facade.serviceV2.crm.MnCrmIf002V2ServiceImpl.class).batchUpdateCompanyScItemExtend(companyScItemExtendMap);
            } catch (Throwable e) {
                log.error("MnCrmIf002ServiceImpl#externalUpdateReplySalePlan_occor_error ", e);
                throw e;
            }
       }

        MnCrmCommSDO commSDO = MnCrmCommSDO.builder().resultType(MnSAPStatus.SUCCESS.getCode()).resultMessage("月度计划回复成功").build();
        if(CollectionUtils.isNotEmpty(eCommerceSalesPlanReplay) && commerceErrMsg!=null){
            resultMap.put("电商月度计划回复出错",commerceErrMsg);
        }
        if(resultMap.size() > 0){
            String resultMessage = JSON.toJSONString(resultMap);
            commSDO = MnCrmCommSDO.builder().resultType(MnSAPStatus.ERROR.getCode()).resultMessage(resultMessage).build();
        }
        commResponse.setData(commSDO);
        return commResponse;
    }


    @ProcessInvoker(remark = "omniPlanReplyExtend", errorCode = "OTS-02-007-00-16-999", printLog = true)
    @Override
    public Result<Boolean> omniPlanReplyExtend(OmniPlanReplyExtendRequest omniPlanReplyExtendRequest){
        LoadSalesPlanListRequest queryPlanReq = LoadSalesPlanListRequest.builder()
                .planNo(omniPlanReplyExtendRequest.getPlanNo())
                .status(2)
                .build();
        Result<List<SalesPlan>> queryPlanResult = getSalesPlanList(queryPlanReq);
        if (null == queryPlanResult || CollectionUtils.isEmpty(queryPlanResult.getResult())) {
            return Result.fail("-1","未查询到待回复的计划");
        }
        SalesPlan salesPlan = queryPlanResult.getResult().get(0);

        BatchQueryByBizIdRequest bizIdRequest = new BatchQueryByBizIdRequest();
        bizIdRequest.setPlanId(salesPlan.getId().toString());
        bizIdRequest.setPoolType("2");
        bizIdRequest.setBizType("5");
        bizIdRequest.setStart(0);
        bizIdRequest.setLimit(1000);
        Result<List<PlanScItem>> reportPlanScItemsResult = getPlanScItemList(bizIdRequest);
        if (null == reportPlanScItemsResult || CollectionUtils.isEmpty(reportPlanScItemsResult.getResult())) {
            return Result.fail("-1","未查询到提报货品");
        }
        List<PlanScItem> reportPlanScItems = reportPlanScItemsResult.getResult();
        Map<String, PlanScItem> reportPlanScItemsMap = reportPlanScItems.stream().collect(Collectors.toMap(PlanScItem::getScItemCode, o -> o));

        //回复货品匹配提报货品
        List<PlanScItemReturnCountSDO> reqList = convertListObj(omniPlanReplyExtendRequest.getPlanScItemList(), PlanScItemReturnCountSDO.class);
        List<PlanScItem> matchResult = new ArrayList<>();
        for (PlanScItemReturnCountSDO replyScItem : reqList) {
            PlanScItem planScItem = reportPlanScItemsMap.get(replyScItem.getScItemCode());
            if (planScItem == null) {
                log.info("MnCrmIf002V2ServiceImpl_omniPlanReplyExtend_planScItem_is_null,scItemCode={}",replyScItem.getScItemCode());
                continue;
            }
            planScItem.setMonthFirstReturnCount(replyScItem.getMonthFirstReturnCount().intValue());
            planScItem.setMonthMiddleReturnCount(replyScItem.getMonthMiddleReturnCount().intValue());
            planScItem.setMonthLastReturnCount(replyScItem.getMonthLastReturnCount().intValue());

            planScItem.setM1RollingReturnCount(planScItem.getM1RollingPlanCount());
            planScItem.setM2RollingReturnCount(planScItem.getM2RollingPlanCount());
            planScItem.setM3RollingReturnCount(planScItem.getM3RollingPlanCount());
            planScItem.setMonthFirstTaskCount(planScItem.getMonthFirstReturnCount() != null ? planScItem.getMonthFirstReturnCount() : 0);
            planScItem.setMonthMiddleTaskCount(planScItem.getMonthMiddleReturnCount() != null ? planScItem.getMonthMiddleReturnCount() : 0);
            planScItem.setMonthLastTaskCount(planScItem.getMonthLastReturnCount() != null ? planScItem.getMonthLastReturnCount() : 0);
            planScItem.setTaskCount(planScItem.getMonthFirstTaskCount() + planScItem.getMonthMiddleTaskCount() + planScItem.getMonthLastTaskCount());

            if (planScItem.getOutboundPrice() != null) {
                planScItem.setTaskOutboundMoney(planScItem.getTaskCount()*planScItem.getOutboundPrice());
                planScItem.setAdjustOutboundMoney(planScItem.getAdjustCount()*planScItem.getOutboundPrice());
            }

            if (planScItem.getCostInsuranceFreight() != null) {
                planScItem.setBeforeTaskMoney(planScItem.getTaskCount() * planScItem.getCostInsuranceFreight());

                if (StringUtils.isNotBlank(salesPlan.getFeatures())) {
                    JSONObject jsonObject = JSONObject.parseObject(salesPlan.getFeatures());
                    if (jsonObject.getString("estimateDiscount") != null) {
                        BigDecimal estimateDiscount = new BigDecimal(jsonObject.get("estimateDiscount").toString());
                        planScItem.setTaskMoney(calculateTaskMoney(estimateDiscount, planScItem.getBeforeTaskMoney()));
                    }
                }
            }

            // 差量 = 计划量-回复量
            Integer monthCount = planScItem.getMonthCount()!=null ? planScItem.getMonthCount() : 0;
            Integer monthReturnCount = planScItem.getMonthFirstReturnCount() + planScItem.getMonthMiddleReturnCount() + planScItem.getMonthLastReturnCount();
            planScItem.setContractDifferenceCount(monthCount - monthReturnCount);
            planScItem.setContractSatisfaction(CalculatePercentage.retainTwo(planScItem.getTaskMoney() != null ? planScItem.getTaskMoney() : 0, planScItem.getMonthContractMoney() != null ? planScItem.getMonthContractMoney() : 0));
            planScItem.setBeforeContractSatisfaction(CalculatePercentage.retainTwo(planScItem.getBeforeTaskMoney() != null ? planScItem.getBeforeTaskMoney() : 0, planScItem.getBeforeMonthContractMoney() != null ? planScItem.getBeforeMonthContractMoney() : 0));

            matchResult.add(planScItem);
        }

        // batchSavePlanScItemExtend参数构建
        List<PlanScItemExtend> extendList = matchResult.stream().map(it -> {
            PlanScItemExtend planScItemExtend = new PlanScItemExtend();
            BeanUtils.copyProperties(it, planScItemExtend);

            Long monthFirstReturnCount = Objects.isNull(it.getMonthFirstReturnCount()) ? 0L : it.getMonthFirstReturnCount().longValue();
            Long monthMiddleReturnCount = Objects.isNull(it.getMonthMiddleReturnCount()) ? 0L : it.getMonthMiddleReturnCount().longValue();
            Long monthLastReturnCount = Objects.isNull(it.getMonthLastReturnCount()) ? 0L : it.getMonthLastReturnCount().longValue();

            planScItemExtend.setMonthFirstReturnCount(monthFirstReturnCount.intValue());
            planScItemExtend.setMonthMiddleReturnCount(monthMiddleReturnCount.intValue());
            planScItemExtend.setMonthLastReturnCount(monthLastReturnCount.intValue());

            planScItemExtend.setMonthFirstCompanyTaskCount(monthFirstReturnCount.intValue());
            planScItemExtend.setMonthMiddleCompanyTaskCount(monthMiddleReturnCount.intValue());
            planScItemExtend.setMonthLastCompanyTaskCount(monthLastReturnCount.intValue());
            Long companyTaskCount = monthFirstReturnCount+monthMiddleReturnCount+monthLastReturnCount;
            planScItemExtend.setCompanyTaskCount(companyTaskCount.intValue());

            // 计算上中下旬回复金额
            Long costInsuranceFreight = Objects.isNull(it.getCostInsuranceFreight()) ? 0L : it.getCostInsuranceFreight();

            planScItemExtend.setMonthFirstReturnMoney(costInsuranceFreight * monthFirstReturnCount.intValue());
            planScItemExtend.setMonthMiddleReturnMoney(costInsuranceFreight * monthMiddleReturnCount.intValue());
            planScItemExtend.setMonthLastReturnMoney(costInsuranceFreight * monthLastReturnCount.intValue());

            planScItemExtend.setGmtCreate(new Date());
            planScItemExtend.setGmtModified(new Date());
            planScItemExtend.setModel(1);
            planScItemExtend.setModelId(String.valueOf(planScItemExtend.getPlanId()));
            return planScItemExtend;
        }).collect(Collectors.toList());

        BatchSavePlanScItemExtendRequest batchSavePlanScItemExtendReq = BatchSavePlanScItemExtendRequest.builder().request(extendList).build();
        log.info("MnCrmIf002V2ServiceImpl_omniPlanReplyExtend_batchSavePlanScItemExtend,req={}",JSONObject.toJSONString(batchSavePlanScItemExtendReq));
        BatchSavePlanScItemExtendResponse response = planScItemExtendService.batchSavePlanScItemExtend(batchSavePlanScItemExtendReq);
        log.info("MnCrmIf002V2ServiceImpl_omniPlanReplyExtend_batchSavePlanScItemExtend,Response={}",JSONObject.toJSONString(response));

        SalesPlan plan = new SalesPlan();
        plan.setId(salesPlan.getId());
        plan.setStatus(3);
        UpdateSalesPlanResponse updateSalesPlan = salesPlanService.updateSalesPlan(plan);
        if (null == updateSalesPlan || updateSalesPlan.getCount() < 1) {
            log.error("MnCrmIf002V2ServiceImpl_omniPlanReplyExtend_updateSalesPlan_fail={}", JSONObject.toJSONString(updateSalesPlan));
            throw new FacadeException("更新计划状态失败");
        }
        return Result.success(true);
    }

    @EpochTransactional(appCode = "bc_order", dataSourceCode = "cr_ots", dataSourceType = "app")
    public void batchUpdateCompanyScItemExtend(Map<String, List<PlanScItemExtend>> companyScItemExtendMap) {
        if (MapUtils.isEmpty(companyScItemExtendMap)) {
            return;
        }

        for (String key : companyScItemExtendMap.keySet()) {
            List<PlanScItemExtend> extendList = companyScItemExtendMap.get(key);
            SalesPlan plan = new SalesPlan();
            plan.setId(Long.valueOf(extendList.get(0).getPlanId()));
            plan.setStatus(3);
            // 3、更新业务单元维度的回复量
            UpdateSalesPlanResponse updateSalesPlan = salesPlanService.updateSalesPlan(plan);
            if (null == updateSalesPlan || updateSalesPlan.getCount() < 1) {
                log.error("MnCrmIf002ServiceImpl#externalUpdateReplySalePlan_fail -更新月度计划失败，{}", JSONObject.toJSONString(updateSalesPlan));
                throw new FacadeException("更新计划状态失败");
            }

            BatchSavePlanScItemExtendRequest itemExtendRequest = BatchSavePlanScItemExtendRequest.builder().request(extendList).build();
            BatchSavePlanScItemExtendResponse batchSavePlanScItemExtendResponse = planScItemExtendService.batchSavePlanScItemExtend(itemExtendRequest);
            if (null == batchSavePlanScItemExtendResponse || batchSavePlanScItemExtendResponse.getCount() != extendList.size()) {
                log.error("MnCrmIf002ServiceImpl#externalUpdateReplySalePlan_fail -更新scItemExtend数量不匹配, extendList=" + extendList + ", response=" + batchSavePlanScItemExtendResponse);
                throw new FacadeException("更新scItemExtend失败");
            }
        }
    }

    private String processCommerceSalesPlan(List<MnCrmIf002SDO> eCommerceSalesPlanReplay) {
        // 根据编码查组织
        BaselineGetOrganizationByCodes2Response organizationResult = baseDataService.baselineGetOrganizationByCodes2(BaselineGetOrganizationByCodes2Request.builder().ids(Lists.newArrayList("1171")).build());
        if (null == organizationResult || CollectionUtils.isEmpty(organizationResult.getResult())) {
            return "电商月度计划回复成功失败，电商销售组织:" + 1171 + "没有在业务组织上维护或已禁用";
        }
        OrganizationSDO salesOrganization = organizationResult.getResult().get(0);
        // 根据组织里的parentId查业务单元
        Result<OrganizationSDO> organization = baseDataService.baselineGetOrganizationById2(BaselineGetOrganizationById2Request.builder().id(salesOrganization.getParentId()).build());
        if (null == organization || null == organization.getResult()) {
            return "电商月度计划回复成功失败，电商销售组织:" + 1171 + "没有维护业务单元";
        }
        OrganizationSDO orgBusiness = organization.getResult();
        int sucNum = 0;
        for (MnCrmIf002SDO mnCrmIf002SDO : eCommerceSalesPlanReplay) {
            try {
                mnCrmIf002SDO.setSalesOrganizationCode(salesOrganization.getId());
                if (!checkObjectAllFields(mnCrmIf002SDO)) {
                    continue;
                }
                // 计划年月转换为时间戳
                long time = new SimpleDateFormat("yyyyMM").parse(mnCrmIf002SDO.getPlanTime().replace("-", "")).getTime();
                mnCrmIf002SDO.setPlanTime(String.valueOf(time));
                MonthlyPlanOfCcommerceLoadListRequest request = new MonthlyPlanOfCcommerceLoadListRequest();
                request.setPlanTime(mnCrmIf002SDO.getPlanTime());
                request.setOrgSaleOrganizationCode(mnCrmIf002SDO.getSalesOrganizationCode());
                request.setScItemGroupCode(mnCrmIf002SDO.getScItemGroup());
                request.setOuterId(mnCrmIf002SDO.getScItemCode());
                request.setCustomerCode(mnCrmIf002SDO.getCustomerCode());
                Result<List<MonthlyPlanOfCcommerce>> listResult = monthlyPlanOfCcommerceService.loadList(request);
                if (null != listResult && CollectionUtils.isNotEmpty(listResult.getResult())) {
                    // 更新
                    MonthlyPlanOfCcommerce monthlyPlanOfCcommerce = convertMonthlyPlanOfCommerce(mnCrmIf002SDO, orgBusiness);
                    monthlyPlanOfCcommerce.setId(listResult.getResult().get(0).getId());
                    monthlyPlanOfCcommerceService.update(monthlyPlanOfCcommerce);
                }
                if (null != listResult && CollectionUtils.isEmpty(listResult.getResult())) {
                    // 新增
                    MonthlyPlanOfCcommerce monthlyPlanOfCcommerce = convertMonthlyPlanOfCommerce(mnCrmIf002SDO, orgBusiness);
                    monthlyPlanOfCcommerce.setGmtCreate(new Date());
                    monthlyPlanOfCcommerceService.create(monthlyPlanOfCcommerce);
                }
                sucNum++;
            } catch (Throwable e) {
                log.error("MnCrmIf002ServiceImpl#externalUpdateReplySalePlan_occor_error={},monthlyPlanOfCcommerce_sdo={}",e,JSONObject.toJSONString(mnCrmIf002SDO));
            }
        }

        if (sucNum == eCommerceSalesPlanReplay.size()) {
            return null;
        } else {
            StringBuilder msgBuilder = new StringBuilder();
            msgBuilder.append("电商月度计划回复部分成功，请注意排查，详情：").append("成功条数=").append(sucNum).append(",总条数=").append(eCommerceSalesPlanReplay.size());
            log.error("MnCrmIf002ServiceImpl#externalUpdateReplySalePlan_fail " + msgBuilder.toString());
            return msgBuilder.toString();
        }
    }

    private List<PlanScItem> getPlanScItemListByTimeAndBusiness(String orgBusinessUnitCode,
                                                                MnCrmIf002SDO crmIf002SDO,
                                                                Map<String, SalesPlan> orgUnitSalePlanMap) {
        // 2.1获取月度计划planId
        long time = getPlanTime(crmIf002SDO);
        LoadSalesPlanListRequest planListRequest = LoadSalesPlanListRequest.builder()
                .planTime(String.valueOf(time))
                .orgBusinessUnitCode(orgBusinessUnitCode)
                .status(2)
                .model(1)
                .build();
        Result<List<SalesPlan>> salesPlanList = getSalesPlanList(planListRequest);
        if (null == salesPlanList || CollectionUtils.isEmpty(salesPlanList.getResult())) {
            log.error("MnCrmIf002ServiceImpl#externalUpdateReplySalePlan_fail 未查询到待回复的计划,customerCode:{},planTime:{}", crmIf002SDO.getCustomerCode(), crmIf002SDO.getPlanTime());
            return Lists.newArrayList();
        }
        // 2.2、货品外部编码转换为scItemId
        SalesPlan salesPlan = salesPlanList.getResult().get(0);

        // 2.3、根据planId、scItemId、bizType、bizId、poolType查询一条业务单元某货品维度的计划明细
        // 构建批量查询计划货品的request
        BatchQueryByBizIdRequest bizIdRequest = BatchQueryByBizIdRequest.builder().build();
        Long planId = salesPlan.getId();
        bizIdRequest.setPlanId(String.valueOf(planId));
        List<String> collect = Lists.newArrayList(orgBusinessUnitCode).stream().filter(Objects::nonNull).collect(Collectors.toList());
        bizIdRequest.setBizIds(collect);
        bizIdRequest.setPoolType("2");
        bizIdRequest.setBizType("5");
        bizIdRequest.setStart(0);
        bizIdRequest.setLimit(1000);
        Result<List<PlanScItem>> reportPlanScItems = getPlanScItemList(bizIdRequest);
        if (CollectionUtils.isEmpty(reportPlanScItems.getResult())) {
            log.error("MnCrmIf002ServiceImpl#externalUpdateReplySalePlan_fail 未查询到提报货品,customerCode:{},planTime:{}", crmIf002SDO.getCustomerCode(), crmIf002SDO.getPlanTime());
            return Lists.newArrayList();
        }
        orgUnitSalePlanMap.put(featchKey(crmIf002SDO), salesPlan);
        return reportPlanScItems.getResult();
    }

    private List<String> getScItemCodesBy002SDOs(List<MnCrmIf002SDO> if002SDOS) {
        Set<String> set = if002SDOS.stream().map(MnCrmIf002SDO::getScItemCode).filter(StringUtils::isNotBlank).collect(Collectors.toSet());
        return Lists.newArrayList(set);
    }

    @Nullable
    private PlanScItem buildPlanScItem(Map<String, PlanScItem> planScItemMap,
                                       Map<String, SalesPlan> orgUnitSalePlanMap,
                                       Map<String, ScItemSDO> scItemMap,
                                       MnCrmIf002SDO mnCrmIf002SDO) {
        ScItemSDO scItemSDO = scItemMap.get(mnCrmIf002SDO.getScItemCode());
        if (Objects.isNull(planScItemMap.get(scItemSDO.getScItemId()))) {
            return null;
        }
        PlanScItem planScItem = planScItemMap.get(scItemSDO.getScItemId());
        planScItem.setMonthFirstReturnCount(SapAndCrmFieldDealUtils.toInteger(mnCrmIf002SDO.getEarlyReportReplyQuantity()));
        planScItem.setMonthMiddleReturnCount(SapAndCrmFieldDealUtils.toInteger(mnCrmIf002SDO.getMiddleReportReplyQuantity()));
        planScItem.setMonthLastReturnCount(SapAndCrmFieldDealUtils.toInteger(mnCrmIf002SDO.getLateReportReplyQuantity()));
        planScItem.setM1RollingReturnCount(SapAndCrmFieldDealUtils.toInteger(mnCrmIf002SDO.getRollingPlanReplyQuantityM1()));
        planScItem.setM2RollingReturnCount(SapAndCrmFieldDealUtils.toInteger(mnCrmIf002SDO.getRollingPlanReplyQuantityM2()));
        planScItem.setM3RollingReturnCount(SapAndCrmFieldDealUtils.toInteger(mnCrmIf002SDO.getRollingPlanReplyQuantityM3()));

        planScItem.setMonthFirstTaskCount(planScItem.getMonthFirstReturnCount() != null ? planScItem.getMonthFirstReturnCount() : 0);
        planScItem.setMonthMiddleTaskCount(planScItem.getMonthMiddleReturnCount() != null ? planScItem.getMonthMiddleReturnCount() : 0);
        planScItem.setMonthLastTaskCount(planScItem.getMonthLastReturnCount() != null ? planScItem.getMonthLastReturnCount() : 0);
        planScItem.setTaskCount(planScItem.getMonthFirstTaskCount() + planScItem.getMonthMiddleTaskCount() + planScItem.getMonthLastTaskCount());
        if (planScItem.getCostInsuranceFreight() != null) {
            planScItem.setBeforeTaskMoney(planScItem.getTaskCount() * planScItem.getCostInsuranceFreight());
        }

        // 2.1获取月度计划planId
        SalesPlan salesPlan = orgUnitSalePlanMap.get(featchKey(mnCrmIf002SDO));
        if (StringUtils.isNotBlank(salesPlan.getFeatures())) {
            JSONObject jsonObject = JSONObject.parseObject(salesPlan.getFeatures());
            if (jsonObject.getString("estimateDiscount") != null) {
                BigDecimal estimateDiscount = new BigDecimal(jsonObject.get("estimateDiscount").toString());
                if (planScItem.getBeforeTaskMoney() != null) {
                    planScItem.setTaskMoney(calculateTaskMoney(estimateDiscount, planScItem.getBeforeTaskMoney()));
                }
            }
        }

        // 002回复的时候计划汇总的任务量为0，赋值给extend要计算到岸金额
        planScItem.setTaskOutboundMoney(planScItem.getTaskCount()*planScItem.getOutboundPrice());
        planScItem.setAdjustOutboundMoney(planScItem.getAdjustCount()*planScItem.getOutboundPrice());

        // 差量 = 计划量-回复量
        Integer monthCount = Objects.isNull(planScItem.getMonthCount()) ? 0 : planScItem.getMonthCount();
        Integer monthReturnCount = planScItem.getMonthFirstReturnCount() + planScItem.getMonthMiddleReturnCount() + planScItem.getMonthLastReturnCount();
        planScItem.setContractDifferenceCount(monthCount - monthReturnCount);
        planScItem.setContractSatisfaction(CalculatePercentage.retainTwo(planScItem.getTaskMoney() != null ? planScItem.getTaskMoney() : 0, planScItem.getMonthContractMoney() != null ? planScItem.getMonthContractMoney() : 0));
        planScItem.setBeforeContractSatisfaction(CalculatePercentage.retainTwo(planScItem.getBeforeTaskMoney() != null ? planScItem.getBeforeTaskMoney() : 0, planScItem.getBeforeMonthContractMoney() != null ? planScItem.getBeforeMonthContractMoney() : 0));
        return planScItem;
    }

    private static Boolean checkObjectAllFields(Object object) {
        if (null == object) {
            return false;
        }
        try {
            for (Field f : object.getClass().getDeclaredFields()) {
                f.setAccessible(true);
                String str = String.valueOf(f.get(object));
                if (f.getName().contains("Quantity")) {
                    if (str == null || Strings.isBlank(str)) {
                        f.set(object, "0");
                    }
                } else {
                    if (str == null) {
                        return false;
                    }
                    if (!f.getName().equals("serialVersionUID")) {
                        str = str.trim();
                        f.set(object, str);
                    }
                }
            }
        } catch (Exception e) {
            log.error(JSONObject.toJSONString(object) + "电商月度计划入参校验失败" + e);
            return false;
        }
        return true;
    }

    private MonthlyPlanOfCcommerce convertMonthlyPlanOfCommerce(MnCrmIf002SDO mnCrmIf002SDO, OrganizationSDO orgBusiness) {
        MonthlyPlanOfCcommerce monthlyPlanOfCcommerce = new MonthlyPlanOfCcommerce();
        monthlyPlanOfCcommerce.setOrgBusinessCode(orgBusiness.getId());
        monthlyPlanOfCcommerce.setPlanTime(mnCrmIf002SDO.getPlanTime());
        monthlyPlanOfCcommerce.setOrgSaleOrganizationCode(mnCrmIf002SDO.getSalesOrganizationCode());
        monthlyPlanOfCcommerce.setCustomerCode(mnCrmIf002SDO.getCustomerCode());
        monthlyPlanOfCcommerce.setScItemGroupCode(mnCrmIf002SDO.getScItemGroup());
        monthlyPlanOfCcommerce.setOuterId(mnCrmIf002SDO.getScItemCode());
        /**
         * 20220418 按产品要求 做出以下调整
         * 上旬计划量=CRM回复接口-上旬审核值 ext1
         * 中旬计划量=CRM回复接口-中旬审核值 ext2
         * 下旬计划量=CRM回复接口-下旬审核值 ext3
         */
        monthlyPlanOfCcommerce.setMonthFirstPlannedQuantity(SapAndCrmFieldDealUtils.toInteger(mnCrmIf002SDO.getExt1()));
        monthlyPlanOfCcommerce.setMonthFirstReturnCount(SapAndCrmFieldDealUtils.toInteger(mnCrmIf002SDO.getEarlyReportReplyQuantity()));
        monthlyPlanOfCcommerce.setMonthMiddlePlannedQuantity(SapAndCrmFieldDealUtils.toInteger(mnCrmIf002SDO.getExt2()));
        monthlyPlanOfCcommerce.setMonthMiddleReturnCount(SapAndCrmFieldDealUtils.toInteger(mnCrmIf002SDO.getMiddleReportReplyQuantity()));
        monthlyPlanOfCcommerce.setMonthLastPlannedQuantity(SapAndCrmFieldDealUtils.toInteger(mnCrmIf002SDO.getExt3()));
        monthlyPlanOfCcommerce.setMonthLastReturnCount(SapAndCrmFieldDealUtils.toInteger(mnCrmIf002SDO.getLateReportReplyQuantity()));
        monthlyPlanOfCcommerce.setMonthPlannedQuantity(monthlyPlanOfCcommerce.getMonthFirstPlannedQuantity() +
                monthlyPlanOfCcommerce.getMonthMiddlePlannedQuantity() + monthlyPlanOfCcommerce.getMonthLastPlannedQuantity());
        monthlyPlanOfCcommerce.setMonthReturnCount(monthlyPlanOfCcommerce.getMonthFirstReturnCount() +
                monthlyPlanOfCcommerce.getMonthMiddleReturnCount() + monthlyPlanOfCcommerce.getMonthLastReturnCount());

        /*//根据客户编码+货品组+销售组织编码+业务渠道(固定20)找到唯一的客户售达方 取其中的销售渠道编码与销售部门编码进行落库
        PageQueryCustomerScopeRequest pageQueryAddressListRequest = new PageQueryCustomerScopeRequest();
        //客户编码
        if (StringUtils.isNotBlank(mnCrmIf002SDO.getCustomerCode())){
            pageQueryAddressListRequest.setCustomerCode(mnCrmIf002SDO.getCustomerCode());
        }
        //货品组
        if (StringUtils.isNotBlank(mnCrmIf002SDO.getScItemGroup())){
            pageQueryAddressListRequest.setItemGroup(mnCrmIf002SDO.getScItemGroup());
        }
        //销售组织编码
        if (StringUtils.isNotBlank(mnCrmIf002SDO.getSalesOrganizationCode())){
            pageQueryAddressListRequest.setOrgSaleOrganizationCode(mnCrmIf002SDO.getSalesOrganizationCode());
        }
        //业务渠道 固定20
        //pageQueryAddressListRequest.setChannelCode("20");
        PageQueryCustomerScopeResponse response = otsPlatformEnhanceService.pageQueryCustomerScope(pageQueryAddressListRequest);
        if (response == null || CollectionUtils.isEmpty(response.getResult())) {
            throw new FacadeException("OTS-01-001-01-16-019");
        }
        Map o = (Map) response.getResult().get(0);
        if (Objects.nonNull(o.get("orgSaleChannelCode"))){
            //渠道编码
            String orgSaleChannelCode = o.get("orgSaleChannelCode").toString();
            monthlyPlanOfCcommerce.setOrgSaleChannelCode(orgSaleChannelCode);
        }
        if (Objects.nonNull(o.get("orgSaleDepartmentCode"))){
            //部门编码
            String orgSaleDepartmentCode = o.get("orgSaleDepartmentCode").toString();
            monthlyPlanOfCcommerce.setOrgSaleDepartmentCode(orgSaleDepartmentCode);
        }*/

        monthlyPlanOfCcommerce.setGmtModified(new Date());
        //上旬汇总量=上旬回复量
        monthlyPlanOfCcommerce.setMonthFirstReviseConfirmCount(SapAndCrmFieldDealUtils.toInteger(mnCrmIf002SDO.getEarlyReportReplyQuantity()));
        //中旬汇总量=中旬回复量
        monthlyPlanOfCcommerce.setMonthMiddleReviseConfirmCount(SapAndCrmFieldDealUtils.toInteger(mnCrmIf002SDO.getMiddleReportReplyQuantity()));
        //下旬汇总量=下旬回复量
        monthlyPlanOfCcommerce.setMonthLastReviseConfirmCount(SapAndCrmFieldDealUtils.toInteger(mnCrmIf002SDO.getLateReportReplyQuantity()));
        //本月汇总量=本月回复量
        monthlyPlanOfCcommerce.setMonthReviseConfirmCount(monthlyPlanOfCcommerce.getMonthReturnCount());
        return monthlyPlanOfCcommerce;
    }

    /**
     * 计算折后金额
     *
     * @param estimateDiscount 计划折后率
     */
    public Long calculateTaskMoney(BigDecimal estimateDiscount, Long beforeMoney) {
        BigDecimal multiply = estimateDiscount.multiply(new BigDecimal("0.01").setScale(2, BigDecimal.ROUND_HALF_UP));
        BigDecimal subtract = new BigDecimal(1).subtract(multiply);
        return new BigDecimal(beforeMoney).multiply(subtract).longValue();
    }

    private Result<List<PlanScItem>> getPlanScItemList(BatchQueryByBizIdRequest bizIdRequest) {
        Result<List<PlanScItem>> listResult = new Result<>();
        try {
            listResult = planScItemService.batchQueryByBizId(bizIdRequest);
        } catch (Exception e) {
            log.error("未找到该公司汇总的的月度计划数据", e);
        }
        return listResult;
    }

    private Result<List<SalesPlan>> getSalesPlanList(LoadSalesPlanListRequest planListRequest) {
        Result<List<SalesPlan>> salesPlanList = new Result<>();
        try {
            salesPlanList = salesPlanService.loadSalesPlanList(planListRequest);
        } catch (Exception e) {
            log.error("未找到待回复的月度计划");
        }
        return salesPlanList;
    }

    private Map<String, ScItemSDO> getScItemByOuterIds(List<String> outerIds) {
        Map<String, ScItemSDO> scItemSDOMap = Maps.newHashMap();
        SearchScItemRequest build = SearchScItemRequest.builder().build();
        List<String> stringList = outerIds.stream().map(it -> {
            String itemCode = it;
            if (StringUtils.isNotBlank(itemCode)) {
                itemCode = itemCode.trim();
                if (itemCode.length() >= 12) {
                    return org.apache.commons.lang.StringUtils.substring(itemCode, itemCode.length() - 12);
                }
            }
            return itemCode;
        }).collect(Collectors.toList());

        List<String> outerId = Lists.newArrayList(stringList);
        Map map = new HashMap();
        map.put("outerIdList", outerId);
        build.setSearchReqDTO(map);
        build.setPageSize(stringList.size());
        Result<List<ScItemSDO>> result = baseDataService.searchScItem(build);
        if (Objects.isNull(result) || CollectionUtils.isEmpty(result.getResult())) {
            log.error("未查询到启用的货品，货品不存在或不可用，scItemCodes：{}", outerIds.toString());
            return scItemSDOMap;
        }
        return result.getResult().stream().collect(Collectors.toMap(ScItemSDO::getOuterId, o -> o));
    }

    private long getPlanTime(MnCrmIf002SDO mnCrmIf002SDO) {
        SimpleDateFormat yyyyMM = new SimpleDateFormat("yyyyMM");
        long time = 0;
        try {
            time = yyyyMM.parse(mnCrmIf002SDO.getPlanTime()).getTime();
        } catch (ParseException e) {
            log.error("日期转换失败");
        }
        return time;
    }

    private String getOrgBusinessUnitCode(MnCrmIf002SDO mnCrmIf002SDO) {
        String orgBusinessUnitCode = "";
        try {
            //根据公司outCode查询出bizId
            BatchQueryCompanyRequest companyRequest = BatchQueryCompanyRequest.builder()
                    .outCode(Lists.newArrayList(mnCrmIf002SDO.getCustomerCode()))
                    .build();
            Map map = (Map) bcOtsService.batchQueryCompany(companyRequest);
            Map result = (Map) map.get("result");
            List<Map> content = (List<Map>) result.get("content");
            if (CollectionUtils.isNotEmpty(content)) {
                Map company = content.get(0);
                String bizId = (String) company.get("id");
                //根据bizId，bizType查询对应的组织id
                BaselineGetOrganizationByTypeRequest byTypeRequest = BaselineGetOrganizationByTypeRequest.builder().type("103").bizId(bizId).bizType("COMPANY").build();
                Map organizationByType = (Map) baseDataService.baselineGetOrganizationByType(byTypeRequest);
                List<Map> orgResultMap = (List<Map>) organizationByType.get("result");
                if (CollectionUtils.isNotEmpty(orgResultMap)) {
                    orgBusinessUnitCode = (String) ((Map) (orgResultMap.get(0).get("organizationSDO"))).get("id");
                }
            }
        } catch (Exception e) {
            log.error("MnCrmIf002ServiceImpl#externalReplySalePlan_fail 组织转换异常", e);
        }
        return orgBusinessUnitCode;
    }

    private String featchKey(MnCrmIf002SDO mnCrmIf002SDO){
        StringBuilder key = new StringBuilder();
        key.append(mnCrmIf002SDO.getPlanTime());
        key.append("#");
        key.append(mnCrmIf002SDO.getCustomerCode());
        return key.toString();
    }


    private <T> List<T> convertListObj(List list,Class<T> c) {
        if (org.springframework.util.CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }

        List<T> resultList = new ArrayList<T>();
        for (Object o : list) {
            T t = null;
            try {
                t = c.newInstance();
                org.apache.commons.beanutils.BeanUtils.populate(t,  (Map)o);
            } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
                log.error("omniPlanReplyExtend_convertListObj_eroor",e);
                continue;
            }
            resultList.add(t);
        }
        return resultList;
    }


}
